package com.hb.repository;

import com.hb.model.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class EmployeeRepo {
    @Autowired
    private DataSource dataSource;

    // 使用 JDBC 查询数据时导致样板式代码（JDBC 跟 .NET 里的 ADO.NET 是一样功能的框架，同时 ADO.NET 也会产生类似的样板式代码）
    // JDBC 不是产生样板式代码的唯一场景。在许多编程场景中往往都会导致类似的样板式代码，JMS、JNDI 和使用 REST 服务通常也涉及大量的重复代码。
    public Employee getEmployeeById(long id) {
        Connection conn = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        try {
            conn = dataSource.getConnection();
            // 只有下面这些少量的代码与查询员工逻辑有关系，其他代码都是 JDBC 的样板式代码
            statement = conn.prepareStatement("select id,firstname,lastname,salary from employee where id=?");
            statement.setLong(1, id);
            // PreparedStatement 相当于 ADO.NET 的 SqlCommand
            rs = statement.executeQuery();
            Employee employee = null;
            if (rs.next()) {
                employee = new Employee();
                employee.setId((rs.getLong("id")));
                employee.setFirstName(rs.getString("firstname"));
                employee.setLastName(rs.getString("lastname"));
                employee.setSalary(rs.getBigDecimal("salary"));
            }
            return employee;
        } catch (SQLException e) {  // 必须捕捉 SQLException，因为它是一个检查型异常
            System.out.println(e.getMessage());
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    System.out.println(e.getMessage());
                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    System.out.println(e.getMessage());
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
        return null;
    }

    @Autowired
    private JdbcTemplate jdbcTemplate;

    // Spring 旨在通过模板封装来消除样板式代码。Spring 的 JdbcTemplate 使得执行数据库操作时，避免传统的 JDBC 样板代码成为了可能。
    // 使用 Spring 的 JdbcTemplate（利用了 Java 5 特性[什么特性？？？]的 JdbcTemplate 实现）重写的 getEmployeeById() 方法仅仅关注于获取员工数据的核心逻辑，
    // 而不需要迎合 JDBC API 的需求。
    public Employee getEmployeeById4Spring(long id) {
        return jdbcTemplate.queryForObject("select id,firstname,lastname,salary from employee where id=?", new RowMapper<Employee>() {
            @Override
            public Employee mapRow(ResultSet resultSet, int i) throws SQLException {
                Employee employee = new Employee();
                employee.setId((resultSet.getLong("id")));
                employee.setFirstName(resultSet.getString("firstname"));
                employee.setLastName(resultSet.getString("lastname"));
                employee.setSalary(resultSet.getBigDecimal("salary"));
                return employee;
            }
        }, id);
    }
}
